package com.iwuyc.tools.commons.util.collection;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author Neil
 * @since 2017年10月15日
 */
public class ArrayUtil {
    private ArrayUtil() {
    }

    /**
     * 是否数组。
     * <pre>
     * example:
     *   arrays == null : true
     *   arrays.length == 0 : trues
     * </pre>
     *
     * @param arrays 待判断的数组
     * @param <T>    数组对应的实际类型
     * @return 如果数组为null或者长度为0，则返回true，否则返回false
     */
    public static <T> boolean isEmpty(T[] arrays) {
        return null == arrays || arrays.length == 0;
    }

    /**
     * 判断数组是否不为null。跟 {@link ArrayUtil#isEmpty(Object[])} 值相反
     *
     * @param arrays 带判断的数组
     * @param <T>    数组对应的实际类型
     * @return 如果数组不为null或者长度不为0，则返回true，否则返回false
     * @see ArrayUtil#isEmpty(Object[])
     */
    public static <T> boolean isNotEmpty(T[] arrays) {
        return !isEmpty(arrays);
    }

    /**
     * 判断long[]数组是否为null，或者长度是否为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays为null，或者长度为0，则返回true，否则返回false
     */
    public static boolean isEmpty(long[] arrays) {
        return null == arrays || 0 == arrays.length;
    }

    /**
     * 跟函数 {@link #isEmpty(long[])} 取值相反
     *
     * @param arrays 待判断的数组
     * @return 如果arrays不为null，或者长度不为0，则返回true，否则返回false。
     * @see #isEmpty(long[])
     */
    public static boolean isNotEmpty(long[] arrays) {
        return !isEmpty(arrays);
    }

    /**
     * 判断int[]数组是否为null，或者长度是否为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays为null或者长度为0，则返回true，否则返回false。
     */
    public static boolean isEmpty(int[] arrays) {
        return null == arrays || 0 == arrays.length;
    }

    /**
     * 判断int[]数组是否不为null，或者长度不为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays不为null，或者长度不为0，则返回true，否则返回false
     */
    public static boolean isNotEmpty(int[] arrays) {
        return !isEmpty(arrays);
    }

    /**
     * 判断short[]数组是否为null，或者长度是否为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays为null，或者长度为0，则返回true，否则返回false
     */
    public static boolean isEmpty(short[] arrays) {
        return null == arrays || 0 == arrays.length;
    }

    /**
     * 判断short[]数组是否不为null，或者长度不为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays不为null，或者长度不为0，则返回true，否则返回false
     */
    public static boolean isNotEmpty(short[] arrays) {
        return !isEmpty(arrays);
    }

    /**
     * 判断byte[]数组是否为null，或者长度是否为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays为null，或者长度为0，则返回true，否则返回false
     */
    public static boolean isEmpty(byte[] arrays) {
        return null == arrays || 0 == arrays.length;
    }

    /**
     * 判断byte[]数组是否不为null，或者长度不为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays不为null，或者长度不为0，则返回true，否则返回false
     */
    public static boolean isNotEmpty(byte[] arrays) {
        return !isEmpty(arrays);
    }

    /**
     * 判断float[]数组是否为null，或者长度是否为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays为null，或者长度为0，则返回true，否则返回false
     */
    public static boolean isEmpty(float[] arrays) {
        return null == arrays || 0 == arrays.length;
    }

    /**
     * 判断float[]数组是否不为null，或者长度不为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays不为null，或者长度不为0，则返回true，否则返回false
     */
    public static boolean isNotEmpty(float[] arrays) {
        return !isEmpty(arrays);
    }

    /**
     * 判断double[]数组是否为null，或者长度是否为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays为null，或者长度为0，则返回true，否则返回false
     */
    public static boolean isEmpty(double[] arrays) {
        return null == arrays || 0 == arrays.length;
    }

    /**
     * 判断double[]数组是否不为null，或者长度不为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays不为null，或者长度不为0，则返回true，否则返回false
     */
    public static boolean isNotEmpty(double[] arrays) {
        return !isEmpty(arrays);
    }

    /**
     * 判断char[]数组是否为null，或者长度是否为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays为null，或者长度为0，则返回true，否则返回false
     */
    public static boolean isEmpty(char[] arrays) {
        return null == arrays || 0 == arrays.length;
    }

    /**
     * 判断char[]数组是否不为null，或者长度不为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays不为null，或者长度不为0，则返回true，否则返回false
     */
    public static boolean isNotEmpty(char[] arrays) {
        return !isEmpty(arrays);
    }

    /**
     * 判断boolean[]数组是否为null，或者长度是否为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays为null，或者长度为0，则返回true，否则返回false
     */
    public static boolean isEmpty(boolean[] arrays) {
        return null == arrays || 0 == arrays.length;
    }

    /**
     * 判断boolean[]数组是否不为null，或者长度不为0
     *
     * @param arrays 待判断的数组
     * @return 如果arrays不为null，或者长度不为0，则返回true，否则返回false
     */
    public static boolean isNotEmpty(boolean[] arrays) {
        return !isEmpty(arrays);
    }

    /**
     * 返回数组实际长度，空指针安全。如果为null，则返回0，否则返回实际长度
     *
     * @param arrays 待处理的数组
     * @param <T>    数组的实际长度
     * @return 数组的长度，如果arrays为null，则返回0，否则返回实际长度
     */
    public static <T> int arrayLength(T[] arrays) {
        return isEmpty(arrays) ? 0 : arrays.length;
    }

    /**
     * 获取long[]数组的实际长度，如果arrays为null，则返回0，否则返回实际长度
     *
     * @param arrays 待处理数组
     * @return arrays如果为null，则返回0，否则返回arrays的实际长度
     */
    public static int arrayLength(long[] arrays) {
        return isEmpty(arrays) ? 0 : arrays.length;
    }

    /**
     * 获取int[]数组的实际长度，如果arrays为null，则返回0，否则返回实际长度
     *
     * @param arrays 待处理数组
     * @return arrays如果为null，则返回0，否则返回arrays的实际长度
     */
    public static int arrayLength(int[] arrays) {
        return isEmpty(arrays) ? 0 : arrays.length;
    }

    /**
     * 获取byte[]数组的实际长度，如果arrays为null，则返回0，否则返回实际长度
     *
     * @param arrays 待处理数组
     * @return arrays如果为null，则返回0，否则返回arrays的实际长度
     */
    public static int arrayLength(byte[] arrays) {
        return isEmpty(arrays) ? 0 : arrays.length;
    }

    /**
     * 获取char[]数组的实际长度，如果arrays为null，则返回0，否则返回实际长度
     *
     * @param arrays 待处理数组
     * @return arrays如果为null，则返回0，否则返回arrays的实际长度
     */
    public static int arrayLength(char[] arrays) {
        return isEmpty(arrays) ? 0 : arrays.length;
    }

    /**
     * 获取short[]数组的实际长度，如果arrays为null，则返回0，否则返回实际长度
     *
     * @param arrays 待处理数组
     * @return arrays如果为null，则返回0，否则返回arrays的实际长度
     */
    public static int arrayLength(short[] arrays) {
        return isEmpty(arrays) ? 0 : arrays.length;
    }

    /**
     * 获取float[]数组的实际长度，如果arrays为null，则返回0，否则返回实际长度
     *
     * @param arrays 待处理数组
     * @return arrays如果为null，则返回0，否则返回arrays的实际长度
     */
    public static int arrayLength(float[] arrays) {
        return isEmpty(arrays) ? 0 : arrays.length;
    }

    /**
     * 获取double[]数组的实际长度，如果arrays为null，则返回0，否则返回实际长度
     *
     * @param arrays 待处理数组
     * @return arrays如果为null，则返回0，否则返回arrays的实际长度
     */
    public static int arrayLength(double[] arrays) {
        return isEmpty(arrays) ? 0 : arrays.length;
    }

    @SuppressWarnings("unchecked")
    public static <T> T[] merge(T[] one, T[] otherOne) {
        if (null == one || otherOne == null) {
            throw new NullPointerException("[T[]]one or otherOne is null");
        }
        final int oneLength = arrayLength(one);
        final int otherOneLength = arrayLength(otherOne);

        return (T[]) merger(one, oneLength, otherOne, otherOneLength);
    }

    public static byte[] merge(byte[] one, byte[] otherOne) {
        if (null == one || otherOne == null) {
            throw new NullPointerException("[bytes]one or otherOne is null");
        }
        final int oneLength = arrayLength(one);
        final int otherOneLength = arrayLength(otherOne);

        return (byte[]) merger(one, oneLength, otherOne, otherOneLength);
    }

    public static int[] merge(int[] one, int[] otherOne) {
        if (null == one || otherOne == null) {
            throw new NullPointerException("one or otherOne is null");
        }
        final int oneLength = arrayLength(one);
        final int otherOneLength = arrayLength(otherOne);

        return (int[]) merger(one, oneLength, otherOne, otherOneLength);
    }

    @SuppressWarnings("SuspiciousSystemArraycopy")
    private static Object merger(Object one, int oneLength, Object otherOne, int otherOneLength) {
        final int length = oneLength + otherOneLength;

        final Object result = Array.newInstance(one.getClass().getComponentType(), length);
        System.arraycopy(one, 0, result, 0, oneLength);
        System.arraycopy(otherOne, 0, result, oneLength, otherOneLength);
        return result;
    }

    /**
     * 将数组转换成List
     *
     * @param elements 数组
     * @param <T>      数组元素类型
     * @return List
     */
    @SafeVarargs
    public static <T> List<T> asList(T... elements) {
        if (null == elements) {
            return Collections.emptyList();
        }
        return Arrays.asList(elements);
    }
}
